﻿Function Add-EventGroupHandler
{
  [CmdletBinding(DefaultParameterSetName="Number")]
  param
  (
    [parameter(Position=0,
               Mandatory=$True,
               ParameterSetName="Number")]
    [int]
    $Number = -1,

    [parameter(Position=0,
               Mandatory=$True,
               ParameterSetName="FriendlyName")]
    [String]
    $FriendlyName,

    [parameter(Position=0,
               Mandatory=$True,
               ParameterSetName="Order")]
    [int]
    $Order = -1,

    [parameter(Position=0,
               Mandatory=$True,
               ParameterSetName="Id")]
    [System.Guid]
    $Id,

    [parameter(Position=1)]
    [int]
    $HandlerNumber = -1,

    [parameter(Position=2)]
    [String]
    $HandlerFriendlyName,

    [parameter(Position=3)]
    [System.Guid]
    $HandlerId,

    [parameter(Position=4,
               ValueFromPipeline=$True)]
    [EventHandler]
    $Handler
  )

  Begin
  {
    # Lock the group list XML file while editing the event group.
    $Created = $False
    $Script:GroupMutex = New-Object System.Threading.Mutex($True,"eventlib_write_group_xml",[ref]$Created)

    if ($Created -eq $False)
    {
      try `
      {
        $Lock = $Script:GroupMutex.WaitOne(2000)
      }
      catch [System.Threading.AbandonedMutexException] `
      {
        Write-Warning "Caught AbandonedMutexException.  Consider checking the Event Group list for consistency."
      }
    }
    else
    {
      $Lock = $True
    }

    if ($Lock -eq $False)
    {
      $Exception = New-Object System.TimeoutException "Timed out waiting to lock the eventlib_write_group_xml mutex."
      throw $Exception
    }
  }

  Process
  {
    $GroupList = $(Get-EventGroup)

    if ($GroupList -eq $Null)
    {
      $GroupList = @()
    }
    elseif ($GroupList -isnot [system.array])
    {
      $GroupList = @($GroupList)
    }

    # Find the event group.
    if ($Number -ge 0)
    {
      $ToSet = Get-EventGroup -Number $Number
    }
    elseif ($FriendlyName.Length -gt 0)
    {
      $ToSet = Get-EventGroup -FriendlyName $FriendlyName
    }
    elseif ($Id -ne $Null)
    {
      $ToSet = Get-EventGroup -Id $Id
    }
    elseif ($Order -ge 0)
    {
      $ToSet = Get-EventGroup -Order $Order
    }

    # Find the handler we're adding

    if ($Handler -ne $Null)
    {
      $HandlerList = Get-EventHandler -Id $($Handler.Id)
    }
    elseif ($HandlerNumber -ge 0)
    {
      $HandlerList = Get-EventHandler -Number $($HandlerNumber)
    }
    elseif ($HandlerFriendlyName.Length -gt 0)
    {
      $HandlerList = Get-EventHandler -FriendlyName $($HandlerFriendlyName)
    }
    elseif ($HandlerId -ne $Null)
    {
      $HandlerList = Get-EventHandler -Id $($HandlerId)
    }


    # Add the handler to the group.
    if ($ToSet.Count -eq 1)
    {
      $ToSetIndex = $([array]::IndexOf($GroupList,$ToSet))

      if ($HandlerList.Count -eq 1)
      {
        if ($ToSet.AssignedHandlers -notcontains $HandlerList[0].Id)
        {
          $ToSet.AssignedHandlers += $HandlerList[0].Id
        }
        else
        {
          $Exception = New-Object System.ArgumentException "Specified event group already contains '$($HandlerList[0].Id)' as a handler."
          throw $Exception
        }
      }
      else
      {
        $Exception = New-Object System.ArgumentException "$($HandlerList.Count) event handlers matched the given parameters."
        throw $Exception
      }

      $GroupList[$ToSetIndex] = $ToSet
      Export-Clixml -Path $(Join-Path $Script:ModulePath "Data\groups.xml") -InputObject $GroupList

    }
    else
    {
      $Exception = New-Object System.ArgumentException "Fatal error.  $($ToSet.Count) groups matched the given parameters.  Check the group XML file."
      throw $Exception
    }
  }

  End
  {
    $Script:GroupMutex.ReleaseMutex()
  }
}